package com.link2room.blaster.facade.impl;

import com.link2room.aeriabots.dto.callBack.WxCallBackDto;
import com.link2room.aeriabots.dto.param.base.WxComponentParamDto;
import com.link2room.blaster.common.FreemarkerUtil;
import com.link2room.blaster.constant.MsgConstant;
import com.link2room.blaster.dto.param.base.BlasterBaseParamDto;
import com.link2room.blaster.entity.MsgSendLogEntity;
import com.link2room.blaster.entity.MsgTemplate;
import com.link2room.blaster.facade.ISendMsgFacadeService;
import com.link2room.blaster.feign.aeriabots.WxOfiiceialAccountsTokenFeignService;
import com.link2room.blaster.service.IMsgTemplateService;
import com.link2room.common.exception.SysException;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.JacksonUtil;
import com.link2room.common.util.StringUtil;
import com.link2room.common.util.XmlUtil;
import com.link2room.enums.exception.BlasterSysExceptionEnum;
import com.tencent.client.OfficialAccountClient;
import com.tencent.protocol.officialAccount.message.template.send.TemplateSendResDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Created by LN on 2016/9/13.
 */
@Component("sendMsgFacadeService")
public class SendMsgFacadeServiceImpl implements ISendMsgFacadeService {
    private static Logger logger = LoggerFactory.getLogger(SendMsgFacadeServiceImpl.class);
    @Resource
    private ICommonService commonServiceSupport;
    @Autowired
    private WxOfiiceialAccountsTokenFeignService wxOfiiceialAccountsTokenFeignService;
    @Resource
    private IMsgTemplateService msgTemplateService;
    @Override
    public void sendMsg(BlasterBaseParamDto paramDto) throws Exception {
        MsgTemplate template = this.findTemplate(paramDto.getLhotelGroupCode(), paramDto.getLhotelCode(), paramDto.getChannel(), paramDto.getTemplateCode());
        if(MsgConstant.CHANNEL.WECHAT.equals(template.getChannel())){
            this.sendWXMsg(paramDto,template,paramDto.getDataModelMap(),paramDto.getOpenid());
        }

    }
    private static Set MSGID_SET = Collections.synchronizedSet(new HashSet<String>());
    @Override
    public boolean msgCallbackHandle(BlasterBaseParamDto paramDto) throws Exception {
        String msgbody = paramDto.getMsgBody();
        boolean isDone = true;
        WxCallBackDto dto = XmlUtil.fromXML(msgbody, WxCallBackDto.class);
        if(MSGID_SET.contains(dto.getMsgId())){
            //若set中已经有msgid，则此条回调在处理中，这里不做处理
            return isDone;
        }else{
            //set该msgid，防止并发处理同一条msgid
            MSGID_SET.add(dto.getMsgId());

            isDone = this.updateMsgLog(dto);
            //处理结束释放
            MSGID_SET.remove(dto.getMsgId());
        }
        return isDone;
    }
    //跟新msgLog状态
    private boolean updateMsgLog(WxCallBackDto dto) throws Exception {
        if(StringUtil.isBlank(dto.getMsgId())){
            logger.info("WxCallBackDto.msgid is null");
            logger.debug("WxCallBackDto.msgid is null");
            return true;
        }

        MsgSendLogEntity logS = new MsgSendLogEntity();
        logS.setMsgId(dto.getMsgId());
        MsgSendLogEntity log = commonServiceSupport.findOneEQ(MsgSendLogEntity.class, logS);
        if(log == null){
            //未查到 不处理
            return true;
        }
        log.setResult(dto.getStatus());
        commonServiceSupport.merge(log);
        return true;
    }

    private void sendWXMsg(BlasterBaseParamDto paramDto, MsgTemplate template , Map map, String openid) throws Exception {
        if(map != null && map.size() > 0){
            String str = FreemarkerUtil.getMsg(template,map);
            Map dateMap = (Map) JacksonUtil.jsonToBean(str, Map.class);
            String token = this.getOfficialAccountsToken(template.getLhotelGroupCode(),template.getLhotelCode());
            TemplateSendResDate res = OfficialAccountClient.sendTemplateMsg(token, dateMap, template.getTemplateId(), openid);
            this.logSendMsg(paramDto,res,str);
        }
    }

    /**
     * 记录发送的消息
     * @param paramDto
     * @param res
     * @param msg
     * @throws Exception
     */
    private void logSendMsg(BlasterBaseParamDto paramDto, TemplateSendResDate res, String msg) throws Exception {
        MsgSendLogEntity log = new MsgSendLogEntity();
        log.setLhotelCode(paramDto.getLhotelCode());
        log.setLhotelGroupCode(paramDto.getLhotelGroupCode());
        log.setMsgId(res.getMsgid().toString());
        log.setErrMsg(res.getErrmsg());
        log.setMsg(msg);
        log.setErrCode(res.getErrcode());
        commonServiceSupport.save(log);
    }

    /**
     * 查找消息模板
     * @param lhotelGorupCode
     * @param lhotelCode
     * @param channel
     * @param templateCode
     * @return
     * @throws Exception
     */
    private MsgTemplate findTemplate(String lhotelGorupCode ,String lhotelCode ,String channel,String templateCode) throws Exception {
        MsgTemplate s = new MsgTemplate();
        s.setLhotelGroupCode(lhotelGorupCode);
        s.setLhotelCode(lhotelCode);
        s.setChannel(channel);
        s.setCode(templateCode);
        MsgTemplate res = commonServiceSupport.findOneEQ(MsgTemplate.class, s);
        if(res == null){
            throw new SysException(BlasterSysExceptionEnum.NO_TEMPLATE);
        }
        return res;
    }

    private String getOfficialAccountsToken(String lhotelGroupCode,String lhotelCode) throws Exception {
        WxComponentParamDto paramDto = new WxComponentParamDto();
        paramDto.setLhotelGroupCode(lhotelGroupCode);
        paramDto.setLhotelCode(lhotelCode);
        return wxOfiiceialAccountsTokenFeignService.getOfficialAccountsToken(paramDto.paramToMap()).getResultInfo();
    }
}
